﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Zquence_Studio_Port.Conversions
{
    internal class MidiFormatTrackData
    {
        public int[] TrackNameData = new int[]
        {
            0x00, 0xff, 0x03,
            0x00 // Length in chars
        };

        public List<int[]> playEvents = new List<int[]>();
        public string TrackName;

        public MidiFormatTrackData(String trackname)
        {
            SetTrackName(TrackName = trackname);
        }

        public void SetTrackName(String trackname)
        {
            TrackNameData[3] = trackname.Length;

            int[] newTrackNameData = new int[TrackNameData.Length + trackname.Length];
            newTrackNameData[0] = TrackNameData[0];
            newTrackNameData[1] = TrackNameData[1];
            newTrackNameData[2] = TrackNameData[2];
            newTrackNameData[3] = TrackNameData[3];
            for (int i = 0; i < trackname.Length; i++)
            {
                newTrackNameData[4 + i] = trackname[i];
            }
            TrackNameData = newTrackNameData;
        }

        /** Store a note-on event */
        public void noteOn(int delta, int note, int velocity)
        {
            int[] data = new int[4];
            data[0] = delta;
            data[1] = 0x90;
            data[2] = note;
            data[3] = velocity;
            playEvents.Add(data);
        }


        /** Store a note-off event */
        public void noteOff(int delta, int note)
        {
            int[] data = new int[4];
            data[0] = delta;
            data[1] = 0x80;
            data[2] = note;
            data[3] = 0;
            playEvents.Add(data);
        }


        /** Store a program-change event at current position */
        public void progChange(int prog)
        {
            int[] data = new int[3];
            data[0] = 0;
            data[1] = 0xC0;
            data[2] = prog;
            playEvents.Add(data);
        }


        /** Store a note-on event followed by a note-off event a note length
            later. There is no delta value — the note is assumed to
            follow the previous one with no gap. */
        public void noteOnOffNow(int duration, int note, int velocity)
        {
            noteOn(0, note, velocity);
            noteOff(duration, note);
        }


        public void noteSequenceFixedVelocity(int[] sequence, int velocity)
        {
            bool lastWasRest = false;
            int restDelta = 0;
            for (int i = 0; i < sequence.Length; i += 2)
            {
                int note = sequence[i];
                int duration = sequence[i + 1];
                if (note < 0)
                {
                    // This is a rest
                    restDelta += duration;
                    lastWasRest = true;
                }
                else
                {
                    // A note, not a rest
                    if (lastWasRest)
                    {
                        noteOn(restDelta, note, velocity);
                        noteOff(duration, note);
                    }
                    else
                    {
                        noteOn(0, note, velocity);
                        noteOff(duration, note);
                    }
                    restDelta = 0;

                    lastWasRest = false;
                }
            }
        }
    }
}
